package com.mianyang.zhangsan.plugin.oss;

import com.mianyang.zhangsan.exception.SecServiceException;
import io.minio.BucketExistsArgs;
import io.minio.DownloadObjectArgs;
import io.minio.GetObjectArgs;
import io.minio.GetObjectResponse;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveBucketArgs;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;


/**
 * @author jiangjr
 * @date 2022-10-25
 */
@Slf4j
@Component
public class MinioService implements InitializingBean {
    @Autowired
    private MinioConfig config;
    private MinioClient client;

    public boolean bucketIsExists(String bucketName) {
        BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName).build();
        try {
            return client.bucketExists(args);
        } catch (Exception e) {
            log.error("文件服务器异常-{}", e.getMessage());
            throw new SecServiceException("文件服务器异常");
        }
    }


    /**
     * 创建容器
     * @param bucketName 容器名称
     */
    public void createBucket(String bucketName) {
        MakeBucketArgs args = MakeBucketArgs.builder().bucket(bucketName).build();
        try {
            if (!bucketIsExists(bucketName)) {
                client.makeBucket(args);
            }
        } catch (Exception e) {
            log.error("创建文件服务器目录异常-{}", e.getMessage());
            throw new SecServiceException("创建文件服务器目录异常");
        }
    }

    public void removeBucket(String bucketName) {
        RemoveBucketArgs args = RemoveBucketArgs.builder().bucket(bucketName).build();
        try {
            client.removeBucket(args);
        } catch (Exception e) {
            throw new SecServiceException("删除文件服务器目录异常");
        }
    }

    /**
     * 上传文件
     * @param file 文件
     * @param bucketName 容器名称
     */
    public String uploadFile(MultipartFile file, String bucketName) {
        if (bucketName == null) {
            bucketName = config.getDefaultBucket();
        }
        // 拼接唯一的文件名
        String filePath = UUID.randomUUID() + file.getOriginalFilename();
        try {
            InputStream inputStream = file.getInputStream();
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(filePath)
                    .contentType(file.getContentType())
                    .stream(inputStream, inputStream.available(), -1).build();
            client.putObject(args);
        } catch (Exception e) {
            log.error("文件上传服务器异常-{}", e.getMessage());
            throw new SecServiceException("文件上传异常");
        }
        return config.getDownloadUrl() + filePath;
    }

    public void downloadFile(String bucketName, String filePath, String savePath) {
        if (bucketName == null) {
            bucketName = config.getDefaultBucket();
        }
        DownloadObjectArgs args = DownloadObjectArgs.builder()
                .bucket(bucketName)
                .object(filePath)
                .filename(savePath).build();
        try {
            client.downloadObject(args);
        } catch (Exception e) {
            log.error("下载文件异常-{}", e.getMessage());
            throw new SecServiceException("下载文件异常");
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.client = MinioClient.builder().endpoint(config.getEndpoint())
                .credentials(config.getAccessKey(), config.getSecretKey()).build();
    }
}
